perm filename STRUCT.LSP[LSP,JRA] blob sn#099700 filedate 1974-04-30 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00010 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00002 00002	prog	::= struct[defn:decsbdy:form]
C00004 00003	vars	::= seq[var]
C00005 00004	The evaluator
C00008 00005	find[n:vare:environ]
C00009 00006	primitive[f:primitivea:forms]sexpr
C00010 00007	An example:
C00011 00008	evgen({x,y,z},
C00013 00009	Try environ....
C00014 00010	The first version of eval corresponds to the LISP A-LIST eval.
C00015 ENDMK
C⊗;
prog	::= struct[defn:decs;bdy:form]
 
form	::= var
	::= const
	::= conditional
	::= f_app
	::= closure
	::= generic
	
var	::= id

const 	::= primitive
	::= lambda
	::= farg
	::= label
	::= sexpr

sexpr 	::= atom
	::= dtpr

conditional	::= seq[clause]

clause	::= struct[test:form,consequent:form]

f_app	::= struct[op:form;args:forms]

lambda	::= struct[formals:vars;body:form]

label	::= bind

closure ::= form

environ	::= seq[bind]

bind	::= struct[name:var,value;form]

farg	::= struct[fun:form;st:environ]

dtpr	::= struct[car:sexpr;cdr:sepxr]

primitive ::= car
	  ::= cdr
	  ::= cons
	  ::= eq
	  ::= atom

generic	::= struct[dispat:vars;body:matchs]

match	::= struct[pats:pats;repl:form]

pat	::= struct[m:mode;vars:vars]

dec	::= struct[n:var;m:mode]

mode	::= 
vars	::= seq[var]

forms	::= seq[form]

matchs	::= seq[match]

modes	::= seq[mode]

pats	::= seq[pat]

decs	::= seq[dec]

The evaluator

eval[e:form;a:environ]form
 generic(e)
	[var]          => find(e,a)
	[const]        => e
	[conditional]  => evcond(e;a)
	[f_apply(u,v)] => apply(u,evlis(v,a),a)
	[closure(f)]   => farg(f,a)
	[generic(d,mats)] => evgen(d,mats,a)
 end;


apply[f;form;a:forms;st:environ] form
 generic(f)
	[const] => c_apply(f,a,st)
	apply(eval(f,st)a,st)
 end

c_apply[f:const;a:forms;st:environ]form
 generic(f)
	[primitive]    => p-apply(f,a)
	[lambda(v,b)]  => eval(b,environ(binds(v,a),st))
	[label(n,def)] => apply(n,a,environ(binds(n,def)st))
	[farg(f,e)]    => apply(f,a,e)
 end;

evcond[b:conditional;st:environ] form
 on(b)
	[ε] => FALSE;
	[(clause(test,val)⊗c)] => {eval(test,st) => eval(val,st);evcond(c,st)}
 end;

evgen[vs:vars;bdy:matchs;a:environ] form
 on(bdy)
	[ε] => LOSS;
	[(match(u,v)⊗m)] => {chk_modes(u,vs) => eval(v;environ(bindr(u,vs),a))
	evgen(vs,m1,a)
 end;

chk_modes[u:pats;vs:vars] boolean
 on(pats,vars)
	[ε] => TRUE;
	[(pat(m1,*)⊗p),(v⊗w)] => {m1=mode(v) => TRUE}
	chkmode(p,w)
 end;

bindr[u:pats;vs:vars] environ
 on(pats,vars)
	[ε] => ε
	[(pat(*,vs)⊗p),(v⊗w)] => environ(bindr(p,w),bind*(vs,v))
 end;

bind*[vs:vars;v:var] environ

 PRIMITIVE BINDER
    ex. vs = (a,b,c) and v is struct[x:xx;y:yy;z:zz ...]
	then make environ of form ((a . xx),(b . yy) ..)

find[n:var;e:environ]
 on(e)
	[ε]             => LOSS
	[(bind(u,v)⊗w)] => {n=u => v;find(n;w)}
 end;


evlis[args:forms;st:environ] forms
 on(args)
	[ε]     => ε;
	[(a,a1) => forms(eval(a,st),evlis(a1,st))
 end;

binds[vs:vars;as:args]environ
 on(vs,as)
	[ε]             => ε;
	[(v⊗v1),(a⊗a1)] => environ(bind(v,a),binds(v1,a1))
 end;
primitive[f:primitive;a:forms]sexpr
 generic[f]
	[car] => evcar[a]
	...

 end;

evcar[a:forms]sexpr
 on(a)
	[ε]      => LOSS
	[(a,a1)] => LOSS
	car(a)
 end

car[x:dtpr]x.car

cdr[x:dtpr]x.cdr


cons[x:sexpr;y:sexpr] dtpr(x,y)

eq[x:atom;y:atom] boolean
{x=y => TRUE;FALSE}

atom[x;sexpr]boolean
 generic(x)
	[atom] => TRUE
	FALSE
 end;


An example:

let [ ...] be fences for structures and
    { ... } be fences for sequences.

Thus abstract syntax of 
x	::= struct[a:b;c:d]
b 	::= seq[1,2,3]

represents an instance of an x as:

[{1,2,3},d]

Thus 
 generic(x,x,z)
	[t1(a,b)]   => foo(a,b);
	[*,t2(c,d)] => foo1(c,d);
 end

could go to:

  [{x,y,z}, 

	{[{[t1, {a,b)}], ε, ε}, [foo, {a,b}],

	 [{ε, [t1, {c,d)}], ε}, [foo, {c,d}] 
	 }
   ]

now for execution of evgen on hhs.
First the evaluation is intuitive rather than precise we will use values and
variables interchangeably in "calling sequrnce" no confusion should result.
evgen({x,y,z},

      {[{[t1, {a,b)}], ε, ε}, [foo, {a,b}],
       [{ε, [t1, {c,d)}], ε}, [foo, {c,d}] 
       },

	st)          st is name of some envirionment

Note that types match.

(match(  {[t1, {a,b)}], ε, ε}, 
         [foo, {a,b}])  ⊗     {[{ε, [t1, {c,d)}], ε}, [foo, {c,d}] 
				       })

happens now with obvious bindings on u,v, and m.

chkmodes is called:

chkmodes(  {[t1, {a,b)}], ε, ε}, 
           {x,y,z} )

now get
 
(pat(t1,*) ⊗ {ε, ε},  x⊗{y, z}); look at mode of x: is it t1?


assuming it is return TRUE to evgen and perform:

eval( [foo, {a, b}]

      environ( bindr ( {[t1, {a, b)}], ε, ε},

                       {x,y,z} ),
               st) 
      )

Try environ....
   try bindr ....

(pat(*, {a,b}) ⊗{ε,ε}) , (x⊗{y,z}) goes to

	environ( bindr( {ε, ε}, {y,z}),
	         bind*( {a,b} ,x)
	         )

finally should end up at:

environ( ε, bind*( {a,b} ,x))

bind* is primitive and clever. It fetches the data strucure NAMED by x

and associated the appropriate element in that named structure with the
NAMES is the sequence in its frist arg. bind* is to return a data structure
of type "environ". But that's easy and FAST assuming the obvious rep.
for structures and sequences.


The first version of eval corresponds to the LISP A-LIST eval.
Perhaps a more realistic version would be a deep-binding eval.
And here is is:

This should also show what d.s. are necessary for  incestuous implementation.

as usually there is the name-value stack:

stack_ent	::= struct[name:var;mode:mode;value:ptr_any]

first try storing mode of var with var, rather than with value
 reasons: mode is of var not of value;since type checking should
	  handle match. store pure values; accessor  returns mode and value.

find rummages down name stack for name match and return mode-value.